﻿using dreamwork.mobile.app.api.Models.Data;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace dreamwork.mobile.app.api.Infrastructure
{
    public class NormalUserMongoRepository : INormalUserRepository
    {
        private readonly IMongodbContext _context;
        private readonly ILogger<NormalUserMongoRepository> _logger;
        public NormalUserMongoRepository(IMongodbContext context, ILogger<NormalUserMongoRepository> logger)
        {
            _context = context;
            _logger = logger;
        }

        public async Task AddAsync(NormalUser item)
        {
            try
            {
                await _context.NormalUsers.InsertOneAsync(item);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
            }
        }

        public async Task<NormalUser> GetAsync(string id)
        {
            try
            {
                return await _context.NormalUsers
                                .Find(user => user.Id == id)
                                .FirstOrDefaultAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return null;
            }
        }
        public async Task<NormalUser> GetAsync(Expression<Func<NormalUser, bool>> selector)
        {
            try
            {
                var query = _context.NormalUsers.Find(selector);
                return await query.FirstOrDefaultAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return null;
            }
        }
        public async Task<IEnumerable<NormalUser>> GetListAsync(Expression<Func<NormalUser, bool>> selector)
        {
            try
            {
                var query = _context.NormalUsers.Find(selector);
                return await query.ToListAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return null;
            }
        }
        public async Task<IEnumerable<NormalUser>> GetAllAsync()
        {
            try
            {
                return await _context.NormalUsers
                        .Find(_ => true).ToListAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return new List<NormalUser>();
            }
        }

        public async Task<bool> RemoveAsync(string id)
        {
            try
            {
                DeleteResult actionResult
                    = await _context.NormalUsers.DeleteOneAsync(
                        Builders<NormalUser>.Filter.Eq("Id", id));

                return actionResult.IsAcknowledged
                    && actionResult.DeletedCount > 0;
            }
            catch (Exception ex)
            {
                // log or manage the exception
                _logger.LogError(ex, ex.Message);
                return false;
            }
        }

        public async Task<bool> UpdateAsync(NormalUser user)
        {
            var filter = Builders<NormalUser>.Filter.Eq(s => s.Id, user.Id);
            var update = Builders<NormalUser>.Update
                            //.Set(s => s.PhoneNumber, user.PhoneNumber)
                            .Set(s => s.NickName, user.NickName)
                            .Set(s => s.Avatar, user.Avatar)
                            .Set(s => s.Name, user.Name)
                            .Set(s => s.Email, user.Email);

            try
            {
                UpdateResult actionResult
                    = await _context.NormalUsers.UpdateOneAsync(filter, update);

                return actionResult.IsAcknowledged
                    && actionResult.ModifiedCount > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return false;
            }
        }
        public async Task<bool> RemoveAllAsync()
        {
            try
            {
                DeleteResult actionResult
                    = await _context.NormalUsers.DeleteManyAsync(new BsonDocument());

                return actionResult.IsAcknowledged
                    && actionResult.DeletedCount > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return false;
            }
        }
    }
}
